home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Frameworks / TransSkel 3.24 / Demos / C Demos / DialogSkel / DialogSkel.c next >
Text File  |  1995-06-11  |  14KB  |  621 lines

  1. /*
  2.  * DialogSkel - TransSkel modeless dialog demonstration.
  3.  *
  4.  * 21 Apr 88 Version 1.00 Paul DuBois
  5.  * 29 Jan 89 Version 1.01
  6.  * - Conversion for TransSkel 2.0.
  7.  * 07 Jan 91 Version 1.02
  8.  * - Conversion for TransSkel 3.00.
  9.  * 05 Jun 93 Version 1.03
  10.  * - Fixed to compile under THINK C 6.0.
  11.  * 09 Oct 93
  12.  * - Catches suspend/resume events, hides/shows dialogs when these occur.
  13.  * 19 Nov 93
  14.  * - Does better job on suspend/resume.  Rather than using HideWindow() and
  15.  * ShowWindow(), uses ShowHide() to preserve stacking order.
  16.  * - Added regular document window to provide contrast in handling during
  17.  * suspend/resume and to provide a way to bring the application forward by
  18.  * clicking in a window.  (With just dialogs, all the windows are hidden
  19.  * on a suspend.)
  20.  * - Added menu hook to disable Edit menu items when document window is
  21.  * frontmost, since editing doesn't apply to it.
  22.  * - Added Close item to File menu.
  23.  * 09 Dec 93
  24.  * - Updated for TransSkel 3.05.
  25.  * - Flush mouse down on activate when document window wasn't frontmost
  26.  * to preserve stacking order.
  27.  * 30 Dec 93
  28.  * - Fixed bug where closing modeless window by clicking close box caused
  29.  * Visible checkbox to be unchecked in partner, but closing by selecting
  30.  * Close from File menu didn't.
  31.  * 31 Dec 93
  32.  * - Junked all the dialog item manipulation routines and replaced by calls
  33.  * to the equivalent routines that now make up part of the auxiliary
  34.  * component of TransSkel (these routines are new in TS 3.06).
  35.  * 18 Dec 93
  36.  * - Ditto for new 3.07 routines.
  37.  * 11 Feb 94
  38.  * - Minor revisions.
  39.  * 21 Feb 94
  40.  * - Updated for TransSkel 3.11.
  41.  * 23 Apr 94
  42.  * - Updated for TransSkel 3.13.
  43.  * - Since the document window is growable, draw the grow region, which wasn't
  44.  * being done before.
  45.  * 27 Apr 94
  46.  * - Added filter function for modeless dialogs.
  47.  * - Track cursor in edit text item and change to I-beam when inside.
  48.  * - Map return/enter to hits in the Accept button.  Draw bold outline around
  49.  * button.
  50.  * - Controls in dialogs go inactive when window is deactivated.  Added
  51.  * 'dctb' resource for the dialog windows so inactive controls draw in better
  52.  * gray on color monitors.
  53.  * 04 Nov 94
  54.  * - Updated for TransSkel 3.18 (Support for Universal headers, PowerPC,
  55.  * Metrowerks).
  56.  * 21 Mar 95
  57.  * - Updated for TransSkel 3.19.
  58.  */
  59.  
  60. # include    "TransSkel.h"
  61.  
  62.  
  63. # define    normalHilite    0
  64. # define    dimHilite        255
  65.  
  66.  
  67.  
  68. typedef enum            /* menu ID numbers */
  69. {
  70.     fileMenuID = skelAppleMenuID + 1,
  71.     editMenuID
  72. };
  73.  
  74.  
  75. typedef enum
  76. {
  77.     mDlogRes = 1000,
  78.     aboutAlrtRes,        /* About... alert resource number */
  79.     docWindRes = 1000
  80. };
  81.  
  82.  
  83. typedef enum            /* File menu item numbers */
  84. {
  85.     showDlog1 = 1,
  86.     showDlog2,
  87.     showDoc,
  88.     closeWind,
  89.     fGrayLine,
  90.     quit
  91. };
  92.  
  93.  
  94. typedef enum             /* Edit menu item numbers */
  95. {
  96.     undo = 1,
  97.     eGrayLine,
  98.     cut,
  99.     copy,
  100.     paste,
  101.     clear
  102. };
  103.  
  104.  
  105. typedef enum                /* dialog item numbers */
  106. {
  107.     button1 = 1,
  108.     edit1,
  109.     static1,
  110.     radio1,
  111.     radio2,
  112.     radio3,
  113.     check1,
  114.     check2,
  115.     user1
  116. };
  117.  
  118. static pascal void    DrawIcon (DialogPtr dlog, short item);
  119.  
  120.  
  121. static DialogPtr    mDlog1;
  122. static DialogPtr    mDlog2;
  123. static WindowPtr    docWind;
  124. static short        iconNum1 = 0;
  125. static short        iconNum2 = 0;
  126.  
  127. static MenuHandle    fileMenu;
  128. static MenuHandle    editMenu;
  129.  
  130.  
  131. /*
  132.  * Set up a variable to point to the icon drawing procedure.  For 68K code this
  133.  * is just a direct pointers to DrawIcon().  For PowerPC code it is a
  134.  * routine descriptor into which the address of DrawIcon() is stuffed.
  135.  */
  136.  
  137. # if skelPPC        /* PowerPC code */
  138.  
  139. static RoutineDescriptor    drawDesc =
  140.         BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawIcon);
  141. static UserItemUPP    drawIconProc = (UserItemUPP) &drawDesc;
  142.  
  143. # else                /* 68K code */
  144.  
  145. static UserItemUPP    drawIconProc = DrawIcon;
  146.  
  147. # endif
  148.  
  149.  
  150. /* ------------------- */
  151. /* Miscellaneous stuff */
  152. /* ------------------- */
  153.  
  154.  
  155. static pascal void
  156. DrawIcon (DialogPtr dlog, short item)
  157. {
  158. Handle    h;
  159. Rect    r;
  160.  
  161.     SkelGetDlogRect (dlog, item, &r);
  162.     h = GetIcon (dlog == mDlog1 ? iconNum1 : iconNum2);
  163.     PlotIcon (&r, h);
  164. }
  165.  
  166.  
  167. static void
  168. SetDlogRadio (DialogPtr dlog, short item)
  169. {
  170. DialogPtr    partner;
  171. GrafPtr        tmpPort;
  172. Rect        r;
  173.  
  174.     partner = (DialogPtr) GetWRefCon (dlog);
  175.     SkelSetDlogRadioButtonSet (dlog, radio1, radio3, item);
  176.  
  177.     if (partner == mDlog1)
  178.         iconNum1 = item - radio1;
  179.     else
  180.         iconNum2 = item - radio1;
  181.  
  182.     SkelGetDlogRect (partner, user1, &r);
  183.     GetPort (&tmpPort);
  184.     SetPort (partner);
  185.     InvalRect (&r);    /* invalidate item rect to generate update event */
  186.     SetPort (tmpPort);
  187. }
  188.  
  189.  
  190. /* ---------------------------------------- */
  191. /* Dialog window setup and handler routines */
  192. /* ---------------------------------------- */
  193.  
  194.  
  195. static pascal Boolean
  196. DlogFilter (DialogPtr dlog, EventRecord *evt, short *item)
  197. {
  198. Boolean    result = false;
  199. short    hilite;
  200. char    c;
  201. Str255    str;
  202.  
  203.     /*
  204.      * Dim Accept button if edit string is empty.  This must be checked
  205.      * on every event, not just null events.  Otherwise, if the user
  206.      * clears the string and immediately clicks Accept, there would be
  207.      * no intervening null event and the button would be active for the
  208.      * click.
  209.      *
  210.      * Always dim button if this is a deactivate or the dialog isn't
  211.      * frontmost.
  212.      */
  213.  
  214.     SkelGetDlogStr (dlog, edit1, str);
  215.     hilite = (str[0] == 0 ? dimHilite : normalHilite);
  216.     if (evt->what == activateEvt && (evt->modifiers & activeFlag) == 0)
  217.         hilite = dimHilite;
  218.     if (dlog != FrontWindow ())
  219.         hilite = dimHilite;
  220.     if (SkelSetDlogCtlHilite (dlog, button1, hilite))    /* did button change state? */
  221.         SkelDrawButtonOutline (SkelGetDlogCtl (dlog, button1));
  222.  
  223.     switch (evt->what)
  224.     {
  225.     case nullEvent:
  226.         SkelSetDlogCursor (dlog);
  227.         break;
  228.     case keyDown:
  229.         if (SkelDlogMapKeyToButton (dlog, evt, item, button1, 0))
  230.             result = true;
  231.         break;
  232.     case updateEvt:
  233.         SkelDrawButtonOutline (SkelGetDlogCtl (dlog, button1));
  234.         break;
  235.     case activateEvt:
  236.         /* Accept button and outline are set above.  Set other controls here. */
  237.         hilite = (evt->modifiers & activeFlag ? normalHilite : dimHilite);
  238.         (void) SkelSetDlogCtlHilite (dlog, radio1, hilite);
  239.         (void) SkelSetDlogCtlHilite (dlog, radio2, hilite);
  240.         (void) SkelSetDlogCtlHilite (dlog, radio3, hilite);
  241.         (void) SkelSetDlogCtlHilite (dlog, check1, hilite);
  242.         (void) SkelSetDlogCtlHilite (dlog, check2, hilite);
  243.         break;
  244.     }
  245.     return (result);
  246. }
  247.  
  248.  
  249. static pascal void
  250. DlogSelect (DialogPtr actor, short item)
  251. {
  252. DialogPtr    partner;
  253. Str255        title;
  254. short        value;
  255.  
  256.     partner = (DialogPtr) GetWRefCon (actor);
  257.     switch (item)
  258.     {
  259.     case button1:
  260.         SkelGetDlogStr (actor, edit1, title);
  261.         SetWTitle (partner, title);
  262.         break;
  263.  
  264.     /* set radio buttons */
  265.  
  266.     case radio1:
  267.     case radio2:
  268.     case radio3:
  269.         SetDlogRadio (actor, item);
  270.         break;
  271.  
  272.     /* flip check boxes */
  273.  
  274.     case check1:
  275.         if (SkelToggleDlogCtlValue (actor, item))
  276.             ShowWindow (partner);
  277.         else
  278.             HideWindow (partner);
  279.         break;
  280.  
  281.     case check2:
  282.         value = SkelToggleDlogCtlValue (actor, item);
  283.         ((WindowPeek) partner)->goAwayFlag = (char) (value ? 255 : 0);
  284.         break;
  285.     }
  286. }
  287.  
  288.  
  289. static pascal void
  290. DlogClose (void)
  291. {
  292. DialogPtr    actor, partner;
  293.  
  294.     GetPort (&actor);
  295.     partner = (DialogPtr) GetWRefCon (actor);
  296.     HideWindow (actor);
  297.     SkelSetDlogCtlValue (partner, check1, 0);
  298. }
  299.  
  300.  
  301. static pascal void
  302. DlogClobber (void)
  303. {
  304. DialogPtr    dlog;
  305.  
  306.     GetPort (&dlog);
  307.     DisposeDialog (dlog);
  308. }
  309.  
  310.  
  311. static DialogPtr
  312. DemoDialog (StringPtr title, short h, short v)
  313. {
  314. DialogPtr    dlog;
  315.  
  316.     dlog = GetNewDialog (mDlogRes, nil, (WindowPtr) -1L);
  317.     MoveWindow (dlog, h, v, false);
  318.     SetWTitle (dlog, title);
  319.     (void) SkelDialog (dlog, DlogFilter, DlogSelect, DlogClose, DlogClobber);
  320.     return (dlog);
  321. }
  322.  
  323.  
  324. /* ------------------------------------------ */
  325. /* Document window setup and handler routines */
  326. /* ------------------------------------------ */
  327.  
  328.  
  329. static pascal void
  330. DocUpdate (Boolean resized)
  331. {
  332. }
  333.  
  334.  
  335. static pascal void
  336. DocActivate (Boolean active)
  337. {
  338. }
  339.  
  340.  
  341. static pascal void
  342. DocClobber (void)
  343. {
  344.     HideWindow (docWind);
  345.     DisposeWindow (docWind);
  346. }
  347.  
  348.  
  349. static void
  350. DocWindow (short h, short v)
  351. {
  352.     if (SkelQuery (skelQHasColorQD))
  353.         docWind = GetNewCWindow (docWindRes, nil, (WindowPtr) -1L);
  354.     else
  355.         docWind = GetNewWindow (docWindRes, nil, (WindowPtr) -1L);
  356.     (void) SkelWindow (docWind, nil, nil, DocUpdate, DocActivate, nil,
  357.                     DocClobber, nil, false);
  358.     MoveWindow (docWind, h, v, false);
  359. }
  360.  
  361.  
  362. /* ------------- */
  363. /* Menu handlers */
  364. /* ------------- */
  365.  
  366.  
  367. /*
  368.  * Handle selection of About... item from Apple menu
  369.  */
  370.  
  371. static pascal void
  372. DoAppleMenu (short item)
  373. {
  374.     (void) SkelAlert (aboutAlrtRes, SkelDlogFilter (nil, true),
  375.                                             skelPositionOnParentDevice);
  376.     SkelRmveDlogFilter ();
  377. }
  378.  
  379.  
  380. /*
  381.  * File menu handler
  382.  */
  383.  
  384. static pascal void
  385. DoFileMenu (short item)
  386. {
  387.     switch (item)
  388.     {
  389.     case showDlog1:
  390.         SelectWindow (mDlog1);
  391.         ShowWindow (mDlog1);
  392.         SkelSetDlogCtlValue (mDlog2, check1, 1);
  393.         break;
  394.     
  395.     case showDlog2:
  396.         SelectWindow (mDlog2);
  397.         ShowWindow (mDlog2);
  398.         SkelSetDlogCtlValue (mDlog1, check1, 1);
  399.         break;
  400.     
  401.     case showDoc:
  402.         SelectWindow (docWind);
  403.         ShowWindow (docWind);
  404.         break;
  405.  
  406.     case closeWind:
  407.         SkelClose (FrontWindow ());
  408.         break;
  409.  
  410.     case quit:
  411.         SkelStopEventLoop ();
  412.         break;
  413.     }
  414. }
  415.  
  416.  
  417. /*
  418.  * Handle Edit menu
  419.  */
  420.  
  421. static pascal void
  422. DoEditMenu (short item)
  423. {
  424. DialogPtr    dlog;
  425.  
  426.     if (SystemEdit (item - 1))        /* if DA handled operation, return */
  427.         return;
  428.  
  429.     /* if front window is document window, do nothing */
  430.     dlog = (DialogPtr) FrontWindow ();
  431.     if (((WindowPeek) dlog)->windowKind != dialogKind)
  432.         return;
  433.  
  434.     switch (item)
  435.     {
  436.     case cut:
  437.         DialogCut (dlog);
  438.         (void) ZeroScrap ();
  439.         (void) TEToScrap ();
  440.         break;
  441.  
  442.     case copy:
  443.         DialogCopy (dlog);
  444.         (void) ZeroScrap ();
  445.         (void) TEToScrap ();
  446.         break;
  447.  
  448.     case paste:
  449.         (void) TEFromScrap ();
  450.         DialogPaste (dlog);
  451.         break;
  452.  
  453.     case clear:
  454.         DialogDelete (dlog);
  455.         break;
  456.     }
  457. }
  458.  
  459.  
  460. /*
  461.  * Adjust menus when mouse click occurs in menu bar, before
  462.  * menus are shown.
  463.  */
  464.  
  465. static pascal void
  466. AdjustMenus (void)
  467. {
  468. WindowPtr    w = FrontWindow ();
  469.  
  470.     if (w == (WindowPtr) nil)
  471.         DisableItem (fileMenu, closeWind);
  472.     else
  473.         EnableItem (fileMenu, closeWind);
  474.  
  475.     if (w == docWind)
  476.     {
  477.         DisableItem (editMenu, undo);
  478.         DisableItem (editMenu, cut);
  479.         DisableItem (editMenu, copy);
  480.         DisableItem (editMenu, paste);
  481.         DisableItem (editMenu, clear);
  482.     }
  483.     else
  484.     {
  485.         /* modeless dialog or DA -- dim undo for dialogs */
  486.         if (((WindowPeek) w)->windowKind == dialogKind)
  487.             DisableItem (editMenu, undo);
  488.         else
  489.             EnableItem (editMenu, undo);
  490.         EnableItem (editMenu, cut);
  491.         EnableItem (editMenu, copy);
  492.         EnableItem (editMenu, paste);
  493.         EnableItem (editMenu, clear);
  494.     }
  495. }
  496.  
  497.  
  498. /* ---------------------- */
  499. /* Suspend/resume handler */
  500. /* ---------------------- */
  501.  
  502.  
  503. /*
  504.  * On a suspend, hide the dialog windows and deactivate the frontmost window
  505.  * if there is one.  Normally the system will unhilite the front window, but
  506.  * since hiding the dialogs may cause the document window to be hilited, it's
  507.  * necessary to unhilite whatever window's frontmost after hiding the windows.
  508.  *
  509.  * Similarly, on an activate, the system may hilite the frontmost window, but
  510.  * but showing the dialogs may result in a new frontmost window, which then
  511.  * needs to be hilited.  If the document window was not frontmost when the
  512.  * suspend occurred, the system will also generate a mouse click to bring it
  513.  * forward.  To preserve the stacking order, suck the mouse click out of the
  514.  * event queue.
  515.  */
  516.  
  517. static pascal void
  518. SuspendResume (Boolean inForeground)
  519. {
  520. WindowPtr    w;
  521. EventRecord    event;
  522. static Boolean    hidden1;
  523. static Boolean    hidden2;
  524.  
  525.     if (!inForeground)
  526.     {
  527.         hidden1 = hidden2 = false;
  528.         if (((WindowPeek) mDlog1)->visible)
  529.         {
  530.             ShowHide (mDlog1, false);
  531.             hidden1 = true;
  532.         }
  533.         if (((WindowPeek) mDlog2)->visible)
  534.         {
  535.             ShowHide (mDlog2, false);
  536.             hidden2 = true;
  537.         }
  538.         if ((w = FrontWindow ()) != (WindowPtr) nil)
  539.         {
  540.             HiliteWindow (w, false);
  541.             SkelActivate (w, false);
  542.         }
  543.     }
  544.     else
  545.     {
  546.         if ((w = FrontWindow ()) != (WindowPtr) nil)
  547.             HiliteWindow (w, false);
  548.         if (hidden1)
  549.             ShowHide (mDlog1, true);
  550.         if (hidden2)
  551.             ShowHide (mDlog2, true);
  552.         if ((w = FrontWindow ()) != (WindowPtr) nil)
  553.         {
  554.             HiliteWindow (w, true);
  555.             SkelActivate (w, true);
  556.         }
  557.         if (EventAvail (mDownMask, &event))
  558.             (void) GetNextEvent (mDownMask, &event);
  559.     }
  560. }
  561.  
  562.  
  563. /* ------------ */
  564. /* Main program */
  565. /* ------------ */
  566.  
  567.  
  568. int
  569. main (void)
  570. {
  571.     SkelInit ((SkelInitParamsPtr) nil);
  572.  
  573.     SkelSetSuspendResume (SuspendResume);
  574.  
  575.     /* 311 = ellipsis */
  576.     SkelApple ((StringPtr) "\pAbout DialogSkel\311", DoAppleMenu);
  577.  
  578.     fileMenu = NewMenu (fileMenuID, (StringPtr) "\pFile");
  579.     AppendMenu (fileMenu, (StringPtr) "\pShow Dialog 1;Show Dialog 2;Show Doc Window");
  580.     AppendMenu (fileMenu, (StringPtr) "\pClose/W;(-;Quit/Q");
  581.     (void) SkelMenu (fileMenu, DoFileMenu, nil, false, false);
  582.  
  583.     editMenu = NewMenu (editMenuID, (StringPtr) "\pEdit");
  584.     AppendMenu (editMenu, (StringPtr) "\p(Undo/Z;(-;Cut/X;Copy/C;Paste/V;Clear");
  585.     (void) SkelMenu (editMenu, DoEditMenu, nil, false, false);
  586.     
  587.     DrawMenuBar ();
  588.     SkelSetMenuHook (AdjustMenus);
  589.     
  590.     DocWindow (100, 125);
  591.     
  592.     mDlog1 = DemoDialog ((StringPtr) "\pModeless Dialog 1", 50, 50);
  593.     mDlog2 = DemoDialog ((StringPtr) "\pModeless Dialog 2", 150, 200);
  594.     SetWRefCon (mDlog1, (long) mDlog2);
  595.     SetWRefCon (mDlog2, (long) mDlog1);
  596.     SkelSetDlogStr (mDlog1, edit1, (StringPtr) "\pModeless Dialog 2");
  597.     SkelSetDlogStr (mDlog2, edit1, (StringPtr) "\pModeless Dialog 1");
  598.     SkelSetDlogProc (mDlog1, user1, drawIconProc);
  599.     SkelSetDlogProc (mDlog2, user1, drawIconProc);
  600.     SkelSetDlogRadioButtonSet (mDlog1, radio1, radio3, radio1);
  601.     SkelSetDlogRadioButtonSet (mDlog2, radio1, radio3, radio1);
  602.     SkelSetDlogCtlValue (mDlog1, check1, 1);
  603.     SkelSetDlogCtlValue (mDlog2, check1, 1);
  604.     SkelSetDlogCtlValue (mDlog1, check2, 1);
  605.     SkelSetDlogCtlValue (mDlog2, check2, 1);
  606.  
  607.     SelectWindow (docWind);
  608.     ShowWindow (docWind);
  609.     SkelDoEvents (activMask + updateMask);
  610.     SelectWindow (mDlog1);
  611.     ShowWindow (mDlog1);
  612.     SkelDoEvents (activMask + updateMask);
  613.     SelectWindow (mDlog2);
  614.     ShowWindow (mDlog2);
  615.     SkelDoEvents (activMask + updateMask);
  616.  
  617.     SkelEventLoop ();
  618.     SkelCleanup ();
  619. }
  620.  
  621.